package com.alibaba.basic.service.impl;

import com.alibaba.basic.constant.VerifyCodeConstants;
import com.alibaba.basic.dto.BinderDto;
import com.alibaba.basic.dto.SmsDto;
import com.alibaba.basic.exception.BusinessException;
import com.alibaba.basic.service.IVerifyService;
import com.alibaba.basic.util.StrUtils;
import com.alibaba.basic.util.VerifyCodeUtils;
import com.alibaba.user.domain.User;
import com.alibaba.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Service
public class VerifyServiceImpl implements IVerifyService {

    @Autowired
    @Qualifier("redisTemplate")
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public String getImageCode(String key){
        //判断key是否为空
        if (key == null){
            throw new BusinessException("key为空");
        }
        //获取随机验证码
        String code = StrUtils.getComplexRandomString(4);
        //将验证码存放到redis，设置5分钟过期
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);
        //把验证码的值合并到图片，用base64编码。并返回base64编码的字符串
        return VerifyCodeUtils.verifyCode(110,40,code);
    }

    /**
     * 发送图片验证码
     * @param smsDto
     */
    @Override
    public void sendSmsCode(SmsDto smsDto) {
        //1.校验-空值校验
        //2.校验 - 图片验证码校验
        //2.1图片验证码是否过期
        //2.2图片验证码是否正确
        //3.校验 - 手机号是否被注册 - 查询t_user表
        //4.判断原来的验证码是否有效【3分钟过期-redis】，从redis是否能拿到通过key【register:13980062378】
        //4.1如果拿到了，表示有效，继续判断是否过了1分钟重发时间value【9527:14688777777711】
       //4.1.1如果没有过，就不应该再发。提示错误 -- 请勿重发验证码
        //4.1.2如果过了，就使用上次的验证码，但是要刷新过期时间【重新添加redis，用心的时间戳】
        //4.2如果没有拿到，表示验证码过期了
        //4.2.1重新生成验证码，并添加到redis
        //5.调用短信接口发送短信


        //1.校验-空值校验
        String inputImageCode = smsDto.getImageCode();
        String imageCodeKey = smsDto.getImageCodeKey();
        String phone = smsDto.getPhone();
        if (StringUtils.isEmpty(phone)){
            throw new BusinessException("手机号不可为空");
        }
        if (StringUtils.isEmpty(imageCodeKey)){
            throw new BusinessException("请刷新页面重新获取图片验证码");
        }
        if (StringUtils.isEmpty(inputImageCode)){
            throw new BusinessException("图片验证码不能为空");
        }

        //2.校验 - 图片验证码校验
        Object redisImageCode  = redisTemplate.opsForValue().get(imageCodeKey);

        if (redisImageCode  == null){
            throw new BusinessException("图片验证码过期，请重新输入");
        }

        //2.2图片验证码是否正确
        if(!inputImageCode.equalsIgnoreCase(redisImageCode.toString())){
            throw new BusinessException("图形验证码错误!!!");
        }

        //3.校验 - 手机号是否被注册 - 查询t_user表
        User user = userMapper.loadByPhone(phone);
        if (user != null){
            throw new BusinessException("你已经注册，请直接登录，忘记密码请联系管理员");
        }

        //4.判断原来的验证码是否有效【3分钟过期-redis】，从redis是否能拿到通过key【register:13980062378】
        Object redisSmsCode = redisTemplate.opsForValue().get("register:" + phone);
        String code = null;
        if (redisSmsCode == null){//第一次发送or手机验证码过期了
            //过期了就用新的验证码
            code = StrUtils.getComplexRandomString(6);
        } else{
            //没有过期
            //验证是否过了重发时间
            //以前保存的时间
            Long redisTime =Long.parseLong(redisSmsCode.toString().split(":")[1]);
            //现在的时间
            Long nowTime = System.currentTimeMillis();

            //6.没有过期 - 判断是否过了重发时间
            if((nowTime-redisTime)<1*60*1000){//没有过重发时间
                throw new BusinessException("请勿重复获取验证码!!!");
            }else{
                //没有过期就用以前的验证码
                code = redisSmsCode.toString().split(":")[0];
            }
        }

        //7.将验证码存入redis：【register:18725556563 - 9527:1233555555】
        //刷新了过期时间
        redisTemplate.opsForValue().set("register:"+phone,code+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);

        //8.调用SmsUtils发送短信
        //SmsUtil.sendSms(phone,"手机验证码为：" + code + ",请在3分钟内使用!!!");
        System.out.println("手机验证码为：" + code + ",请在3分钟内使用!!!");

    }

    /**
     * 获取微信绑定验证码
     * @param binderDto
     */
    @Override
    public void getBinderSmsCode(BinderDto binderDto) {
        String phone = binderDto.getPhone();

        //1.校验 - 空值校验
        if(StringUtils.isEmpty(phone)){
            throw new BusinessException("手机号码不能为空!!!");
        }


        //5.获取手机验证码 - 判断是否过期 // 9527:1233555555
        Object redisSmsCode = redisTemplate.opsForValue().get(VerifyCodeConstants.BINDER_PREFIX + phone);
        String code = null;
        if(redisSmsCode == null){//第一次发送 or 手机验证码过期了
            //过期了就用新的验证码
            code = StrUtils.getComplexRandomString(6);
        }else{//没有过期
            //验证是否过了重发时间
            //以前保存的时间
            long redisTime = Long.parseLong(redisSmsCode.toString().split(":")[1]);
            //现在的时间
            long nowTime = System.currentTimeMillis();
            //6.没有过期 - 判断是否过了重发时间
            if((nowTime-redisTime)<1*60*1000){//没有过重发时间
                throw new BusinessException("请勿重复获取验证码!!!");
            }else{
                //没有过期就用以前的验证码
                code = redisSmsCode.toString().split(":")[0];
            }
        }

        //7.将验证码存入redis：【register:18725556563 - 9527:1233555555】
        //刷新了过期时间
        redisTemplate.opsForValue().set(VerifyCodeConstants.BINDER_PREFIX + phone,code+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);

        //8.调用SmsUtils发送短信
        //SmsUtil.sendSms(phone,"手机验证码为：" + code + ",请在3分钟内使用!!!");
        System.out.println("手机验证码为：" + code + ",请在3分钟内使用!!!");

    }
}
